﻿using ComLib;
using ComLib.ComFun;
using KInterfaces;
using KWindow.KPageCore;
using KXmlUIControl;
using LogLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace IPCPages
{
    /// <summary>
    /// 等待所有应用程序启动完成页面
    /// </summary>
    public partial class PageStartup : PageControlBase
    {      
        protected List<XmlProgramObject> Programs = null;
        private const string UnknowStatus = "未启动";
        private const string LoadingStatus = "正在启动中";
        private const string StartOKStatus = "启动成功";
        private const string StartFailedStatus = "启动失败";
        private const string NotEnabledStatus = "未启用";
        private List<Image> listIndexImages = new List<Image>();
        private Image imageUnknow = null;
        private Image ImageLoading = null;
        private Image imageStartOK = null;
        private Image imageStartFailed = null;
        private Image imageNotEnabled = null;
        private Point centrePos = new Point(499, 685);
        private Button buttonClose = null;
        private Button buttonOpenTestMode = null;
        private Label labelTip = null;
        private Label labelStatus = null;
      
        public PageStartup()
        {                    
            InitializeComponent();
            SetProcessBase(ProcessStartup.Instance);
        }

        private void ShowStartupFatalError(List<KeyValuePair<string, string>> problems)
        {
            FormShowFatalError form = new FormShowFatalError(problems);
            form.ShowDialog();
        }

        private void ShowStartupLimitedError(List<KeyValuePair<string, string>> problems)
        {
            FormShowLimitedError form = new FormShowLimitedError(problems);
            form.ShowDialog();
        }

        public void OnStartupFinished(AppsStartupResult result, List<KeyValuePair<string, string>> problems)
        {
            if (this.InvokeRequired)
            {
                AfterStartupFinishedHandler handle = new AfterStartupFinishedHandler(OnStartupFinished);
                this.Invoke(handle, new object[] { result, problems });
                return;
            }
            labelStatus.Visible = false;
            switch (result)
            {
                case AppsStartupResult.OK:
                    {
                        Log.WriteAsync("所有应用程序启动已完成, 即将打开默认应用程序.");
                        UpdateData();
                        Process.ToDefaultApp();
                    }
                    break;
                case AppsStartupResult.FatalError:
                    {
                        Log.WriteAsync("应用程序启动发生了关键错误, 即将关闭程序.");
                        buttonClose.Location = centrePos;
                        buttonClose.Visible = true;
                        ShowStartupFatalError(problems);
                        ClearData();
                        countdownControl1.Visible = true;
                        StartCountdown();
                    }
                    break;
                case AppsStartupResult.LimitedError:
                    {
                        Log.WriteAsync("应用程序启动发生了某些错误, 某些功能使用受到限制，如果继续使用仅用于测试，不能正式使用。");                     
                        buttonOpenTestMode.Visible = true;
                        buttonClose.Visible = true;
                        ShowStartupLimitedError(problems);
                        countdownControl1.Visible = true;                       
                        StartCountdown();
                    }
                    break;
                default:
                    break;
            }           
        }

        public string GetStartingStatusString(ProgramStartingStatus s, string msg = "")
        {
            switch (s)
            {
                case ProgramStartingStatus.NotEnabled:
                    return NotEnabledStatus;
                case ProgramStartingStatus.Unknown:
                    return UnknowStatus;
                case ProgramStartingStatus.Loading:
                    return LoadingStatus;
                case ProgramStartingStatus.StartOK:
                    return StartOKStatus;
                case ProgramStartingStatus.StartFailed:
                    return string.Format("{0}, 详情:{1}", StartFailedStatus, msg);
                default:
                    return "未知状态";
            }
        }

        public Image GetStartingStatusImage(ProgramStartingStatus s)
        {
            switch (s)
            {
                case ProgramStartingStatus.NotEnabled:
                    return imageListStatus.Images[0];
                case ProgramStartingStatus.Unknown:
                    return imageListStatus.Images[1];
                case ProgramStartingStatus.Loading:
                    return imageListStatus.Images[2];
                case ProgramStartingStatus.StartOK:
                    return imageListStatus.Images[3];
                case ProgramStartingStatus.StartFailed:
                    return imageListStatus.Images[4];
                default:
                    return null;
            }
        }

        private bool CheckRegCode()
        {
            //检查注册码
            string key = IniConfigFile.IniValue("Info", "kc", "", "");
            string machineCode = "";
            if (!RegCodeCheck.CheckRegCode(key, ref machineCode))
            {
                frmReg frmReg = new frmReg(machineCode);
                var ret = frmReg.ShowDialog();
                if (ret == DialogResult.Cancel)
                {
                    return false;
                }
            }

            return true;
        }
        private void GetControls()
        {
            buttonClose = GetControl<Button>("buttonClose") as Button;
            buttonOpenTestMode = GetControl<Button>("buttonOpenTestMode") as Button;
            labelTip = GetControl<Label>("labelTip") as Label;
            labelStatus = GetControl<Label>("labelStatus") as Label;
            imageUnknow = GetImage("Unknow");
            ImageLoading = GetImage("Loading");
            imageStartOK = GetImage("StartOK");
            imageStartFailed = GetImage("StartFailed");
            imageNotEnabled = GetImage("NotEnabled");
            Assert.IsNotNull(imageUnknow, "imageUnknow is null");
            Assert.IsNotNull(ImageLoading, "ImageLoading is null");
            Assert.IsNotNull(imageStartOK, "imageStartOK is null");
            Assert.IsNotNull(imageStartFailed, "imageStartFailed is null");
            Assert.IsNotNull(imageNotEnabled, "imageNotEnabled is null");
            imageListStatus.Images.Add(imageNotEnabled);
            imageListStatus.Images.Add(imageUnknow);
            imageListStatus.Images.Add(ImageLoading);
            imageListStatus.Images.Add(imageStartOK);
            imageListStatus.Images.Add(imageStartFailed);
            for (int i = 1; i <= 9; i++)
            {
                string key = string.Format("No{0}", i);
                Image img = GetImage(key);
                listIndexImages.Add(img);
                imageListIndexs.Images.Add(img);
            }
        }

        private void InitGridRows()
        {
            //SetGridViewStyles();
            for (int i = 0; i < Programs.Count; i++)
            {
                XmlProgramObject p = Programs[i];
                DataGridViewRow row = new DataGridViewRow();
                row.Height = 64;

                DataGridViewImageCell indexCell = new DataGridViewImageCell();
                indexCell.Value = imageListIndexs.Images[i];
                row.Cells.Add(indexCell);

                DataGridViewTextBoxCell titlecell = new DataGridViewTextBoxCell();
                titlecell.Value = p.Title;
                row.Cells.Add(titlecell);

                DataGridViewCheckBoxCell enabledcell = new DataGridViewCheckBoxCell();
                enabledcell.Value = p.Enable;
                row.Cells.Add(enabledcell);

                DataGridViewImageCell statusCell = new DataGridViewImageCell();
                statusCell.Value = p.Enable ? imageListStatus.Images[1] : imageListStatus.Images[0];
                row.Cells.Add(statusCell);

                DataGridViewTextBoxCell detailcell = new DataGridViewTextBoxCell();
                detailcell.Value = p.Enable ? UnknowStatus : NotEnabledStatus;
                row.Cells.Add(detailcell);

                dataGridView1.Rows.Add(row);
            }
            //dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightBlue;
        }

        private void InvokeInitGridRows()
        {
            Action handler = new Action(InitGridRows);
            this.BeginInvoke(handler);
        }

        public void UpdateGridRowStatus(string programName, ProgramStartingStatus status, string msg)
        {
            if (this.InvokeRequired)
            {
                UpdateProgramStatus handler = new UpdateProgramStatus(UpdateGridRowStatus);
                this.BeginInvoke(handler, new object[] { programName, status, msg });
                return;
            }
            int index = Programs.FindIndex(r => r.Name.Equals(programName));
            if (index == -1)
            {
                Log.WriteAsync("未找到应用程序对象:" + programName);
                return;
            }
            if (dataGridView1.Rows.Count <= index)
            {
                Log.WriteAsync("无效的应用程序对象索引:" + index);
                return;
            }
            DataGridViewRow row = dataGridView1.Rows[index];
            row.Cells[3].Value = GetStartingStatusImage(status);
            row.Cells[4].Value = GetStartingStatusString(status, msg);
        }

        //初始化窗体数据
        public override void InitCtrls()
        {
            base.InitCtrls();
            GetControls();
            InitTips();
            
        }

        private void InitTips()
        {
            labelTip.Text = "模块启动监控";
            int x = (this.Width - labelTip.Width) / 2;
            labelTip.Left = x;

            labelStatus.Text = "应用程序正在启动中，请稍后...";
            x = (this.Width - labelStatus.Width) / 2;
            labelStatus.Left = x;
        }

        /// <summary>
        /// 初始化窗体数据
        /// </summary>
        public override void InitData()
        {
            base.InitData();
            Programs = ShareDataManager.GlobalData.GetValue<List<XmlProgramObject>>("Programs");
            AsyncTask.StartDelayTask(1, ()=> InvokeInitGridRows(), this);
        }

        /// <summary>
        /// 保存窗体数据(窗体本次做完后, 进入下一步之前)
        /// </summary>
        public override void UpdateData()
        {
            base.UpdateData();
        }

        /// <summary>
        /// 清理窗体数据(窗体本次做完后)
        /// </summary>
        public override void ClearData()
        {
            base.ClearData();
          
        }

        /// <summary>
        /// 窗体关闭时
        /// </summary>
        public override void Close()
        {
           
        }

        public override void StartWork()
        {        
            base.StartWork();
        }

        public override void StopWork()
        {
            if (IsMainPage && !CheckRegCode())
            {
                buttonClose_Click(null, null);
                return;
            }
            base.StopWork();
        }

        private void buttonOpenTestMode_Click(object sender, EventArgs e)
        {
            Process.ToHomeApp();
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            Log.WriteAsync("用户启动关闭系统");
            Process.OnTakeAdminAction(AdministratorAction.Exit);
        }
       
        public override void OnCountdownCompleted(object sender, EventArgs e)
        {
           ProcessStartup processStartup = ProcessStartup.Instance;
            switch (processStartup.Result)
            {
                case AppsStartupResult.OK:
                    break;
                case AppsStartupResult.FatalError:                   
                case AppsStartupResult.LimitedError:
                default:
                     {
                        Log.WriteAsync("用户未操作，程序自动关闭系统");
                        Process.OnTakeAdminAction(AdministratorAction.Exit);
                    }
                    return;
            }
        }
    }
}
